package cn.le.service;

import cn.le.beans.dto.JobInfoDTO;
import cn.le.beans.dto.JobNameDTO;
import cn.le.beans.entity.JobInfoPO;
import cn.le.beans.entity.TriggerInfoPO;
import cn.le.beans.vo.JobInfoVO;
import cn.le.dao.JobInfoDAO;
import cn.le.dao.TriggerInfoDAO;
import cn.le.enums.EnStatus;
import cn.le.exception.BizException;
import cn.le.helper.QuartzManager;
import cn.le.util.BeanUtils;
import cn.le.util.IdWorkerUtil;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.le.enums.BUsedData.ONE;

@Service
public class JobInfoService {

    @Autowired
    private JobInfoDAO jobInfoDAO;
    @Autowired
    private TriggerInfoDAO triggerInfoDAO;
    @Autowired
    private QuartzManager quartzManager;

    /**
     * 创建job任务
     * @param jobInfoDTOList
     */
    @Transactional
    public void createJobs(List<JobInfoDTO> jobInfoDTOList) throws BizException {
        //重复验证
        int jobInfoSize = jobInfoDTOList.size();
        if (jobInfoSize > ONE){
            Set<String> nameSet = jobInfoDTOList.stream().map(jobInfoDTO -> jobInfoDTO.getAppName()+jobInfoDTO.getJobName()).collect(Collectors.toSet());
            if (jobInfoSize != nameSet.size()){
                throw new BizException("创建任务失败,任务名称重复");
            }
        }
        List<JobNameDTO> jobNames = new ArrayList<>(jobInfoSize);
        List<JobInfoPO> jobInfos = new ArrayList<>(jobInfoSize);
        List<TriggerInfoPO> triggerInfos = new ArrayList<>(jobInfoSize);
        List<JobInfoVO> jobInfoVOList = new ArrayList<>(jobInfoSize);
        for (int i = 0; i < jobInfoSize; i++) {
            JobInfoDTO jobInfoDTO = jobInfoDTOList.get(i);
            //构建数据库验重对象
            JobNameDTO jobNameDTO = new JobNameDTO(jobInfoDTO.getJobName(),jobInfoDTO.getAppName());
            jobNames.add(jobNameDTO);

            //构建数据库保存job对象
            JobInfoPO jobInfoPO = BeanUtils.copyProperties(JobInfoPO.class,jobInfoDTO);
            long jobId = IdWorkerUtil.getInstance().nextId();
            jobInfoPO.setId(jobId);
            jobInfoPO.setStatus(EnStatus.NORMAL.getType());
            jobInfos.add(jobInfoPO);

            //构建创建任务对象
            JobKey jobKey = quartzManager.getJobKey(jobNameDTO.getJobName(),jobNameDTO.getAppName());
            JobInfoVO jobInfoVO = new JobInfoVO();
            jobInfoVO.setJobInfo(jobInfoDTO);
            jobInfoVO.setJobKey(jobKey);
            jobInfoVOList.add(jobInfoVO);

            //构建创建job触发器对象
            List<String> strategys = jobInfoDTO.getStrategys();
            int size = strategys.size();
            List<TriggerKey> triggerKeyList =  new ArrayList<>(size);
            for (int j = 0;j < size; j++) {
                TriggerKey triggerKey = quartzManager.getTriggerKey(jobInfoDTO.getJobName(),jobInfoDTO.getAppName(),(i+ONE));
                TriggerInfoPO triggerInfoPO = new TriggerInfoPO();
                triggerInfoPO.setId(IdWorkerUtil.getInstance().nextId());
                triggerInfoPO.setJobId(jobId);
                triggerInfoPO.setStatus(EnStatus.NORMAL.getType());
                triggerInfoPO.setTriggerName(triggerKey.getName());
                triggerInfoPO.setStrategy(strategys.get(i));
                triggerInfos.add(triggerInfoPO);

                triggerKeyList.add(triggerKey);
            }
            jobInfoVO.setTriggerKeys(triggerKeyList);
        }
        List<JobInfoPO> jobInfoPOS = findJobInfo(jobNames);
        if (!CollectionUtils.isEmpty(jobInfoPOS)){
            throw new BizException(jobInfoPOS.toString()+"任务已存在");
        }
        //写入任务信息到数据库
        jobInfoDAO.batchInsert(jobInfos);
        triggerInfoDAO.batchInsert(triggerInfos);

        //创建定时任务
        quartzManager.addJobs(jobInfoVOList);

    }

    /**
     * 删除job任务
     */
    @Transactional
    public void deleteJobs(List<JobNameDTO> jobNameDTOList) throws BizException {
        List<JobInfoPO> jobInfoPOList = jobInfoDAO.findJobInfoByStatus(jobNameDTOList,new HashSet<Integer>(){{add(EnStatus.NORMAL.getType());add(EnStatus.SUSPEND.getType());}});
        if (CollectionUtils.isEmpty(jobInfoPOList)){
            throw new BizException("没有正常和暂停任务,删除失败!");
        }
        Set<Long> jobIds = jobInfoPOList.stream().map(JobInfoPO::getId).collect(Collectors.toSet());
        //修改数据库
        jobInfoDAO.updateStatus(jobIds, EnStatus.DELETE.getType());
        triggerInfoDAO.updateStatusByJobIds(jobIds, EnStatus.DELETE.getType());

        //删除quartz中的任务
        int size = jobInfoPOList.size();
        List<JobKey> jobKeyList = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            JobInfoPO jobInfoPO = jobInfoPOList.get(i);
            JobKey jobKey = quartzManager.getJobKey(jobInfoPO.getJobName(),jobInfoPO.getAppName());
            jobKeyList.add(jobKey);
        }
        quartzManager.deleteJobs(jobKeyList);
    }

    /**
     *暂定任务
     * @param jobNameDTOList
     * @throws BizException
     */
    @Transactional
    public void suspendJobs(List<JobNameDTO> jobNameDTOList) throws BizException {
        List<JobInfoPO> jobInfoPOList = jobInfoDAO.findJobInfoByStatus(jobNameDTOList,new HashSet<Integer>(){{add(EnStatus.NORMAL.getType());}});
        if (CollectionUtils.isEmpty(jobInfoPOList)){
            throw new BizException("没有正常任务,暂停失败!");
        }
        Set<Long> jobIds = jobInfoPOList.stream().map(JobInfoPO::getId).collect(Collectors.toSet());
        //修改数据库
        jobInfoDAO.updateStatus(jobIds, EnStatus.SUSPEND.getType());
        triggerInfoDAO.updateStatusByJobIds(jobIds, EnStatus.SUSPEND.getType());
        //暂停任务
        int size = jobInfoPOList.size();
        List<JobKey> jobKeyList = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            JobInfoPO jobInfoPO = jobInfoPOList.get(i);
            JobKey jobKey = quartzManager.getJobKey(jobInfoPO.getJobName(),jobInfoPO.getAppName());
            jobKeyList.add(jobKey);
        }
        quartzManager.suspendJobs(jobKeyList);
    }

    /**
     * 恢复任务
     */
    @Transactional
    public void resumeJobs(List<JobNameDTO> jobNameDTOList) throws BizException {
        List<JobInfoPO> jobInfoPOList = jobInfoDAO.findJobInfoByStatus(jobNameDTOList,new HashSet<Integer>(){{add(EnStatus.SUSPEND.getType());}});
        if (CollectionUtils.isEmpty(jobInfoPOList)){
            throw new BizException("没有暂停任务,恢复失败!");
        }
        Set<Long> jobIds = jobInfoPOList.stream().map(JobInfoPO::getId).collect(Collectors.toSet());
        //修改数据库
        jobInfoDAO.updateStatus(jobIds, EnStatus.NORMAL.getType());
        triggerInfoDAO.updateStatusByJobIds(jobIds, EnStatus.NORMAL.getType());
        //暂停任务
        int size = jobInfoPOList.size();
        List<JobKey> jobKeyList = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            JobInfoPO jobInfoPO = jobInfoPOList.get(i);
            JobKey jobKey = quartzManager.getJobKey(jobInfoPO.getJobName(),jobInfoPO.getAppName());
            jobKeyList.add(jobKey);
        }
        quartzManager.resumeJobs(jobKeyList);
    }

    /**
     * 更新任务
     * @param jobInfoDTOs
     */
    public void rescheduleJobs(List<JobInfoDTO> jobInfoDTOs){




    }


    /**
     * 查询任务信息
     * @return
     */
    public List<JobInfoPO> findJobInfo(List<JobNameDTO> jobNames){
        return jobInfoDAO.findJobInfo(jobNames);
    }

}
